package org.study.mybatis.plus.boot.config;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * 可以看到内容跟使用 JdbcTemplate、Spring Data JPA 的时候是一模一样的。通过 @ConfigurationProperties 可以知道
 * 这两个数据源分别加载了 spring.datasource.primary.* 和 spring.datasource.secondary.* 的配置。@Primary 注解
 * 指定了主数据源，就是当我们不特别指定哪个数据源的时候，就会使用这个 Bean 真正差异部分在下面的JPA配置上。
 * <p>
 * Secondary 数据源的 MyBatis 配置。说明与注意：
 * 1、配置类上使用 @MapperScan 注解来指定当前数据源下定义的 Entity 和 Mapper 的包路径；另外需要指定 sqlSessionFactory 和 sqlSessionTemplate，这两个具体实现在该配置类中类中初始化。
 * 2、配置类的构造函数中，通过 @Qualifier 注解来指定具体要用哪个数据源，其名字对应在 DataSourceConfiguration 配置类中的数据源定义的函数名。
 * 3、配置类中定义 SqlSessionFactory 和 SqlSessionTemplate 的实现，注意具体使用的数据源正确。
 *
 * @author Administrator
 * @date 2021-11-29
 */
@Configuration
@MapperScan(basePackages = "org.study.mybatis.plus.boot.mapper.secondary",
        // 由于这里同时指定了sqlSessionFactoryRef和sqlSessionTemplateRef，所以日志会打印如下警告：
        // Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.
        // 去掉sqlSessionFactoryRef的配置即可
        /*sqlSessionFactoryRef = "secondarySqlSessionFactory",*/
        sqlSessionTemplateRef = "secondarySqlSessionTemplate"
)
public class SecondaryConfig {
    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean(name = "secondarySqlSessionFactory")
    public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(secondaryDataSource);
        MybatisConfiguration configuration = new MybatisConfiguration();
        // 在控制台打印SQL语句
        configuration.setLogImpl(Slf4jImpl.class);
        bean.setConfiguration(configuration);
        // bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/secondary/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "secondarySqlSessionTemplate")
    public SqlSessionTemplate secondarySqlSessionTemplate(@Qualifier("secondarySqlSessionFactory") SqlSessionFactory secondarySqlSessionFactory) throws Exception {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(secondarySqlSessionFactory);
        return sqlSessionTemplate;
    }
}
